package com.joinway.framework.utils.net;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpMessage;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.joinway.framework.utils.DataUtils;
import com.joinway.framework.utils.json.JsonConverter;

public class HttpClientAdaptor {

	private final static Logger log = LoggerFactory.getLogger(HttpClientAdaptor.class);
	
	HttpClient client = HttpClients.createDefault();
	
	public String post(String url) throws Exception {
		return post(url, null, null);
	}
	
	public String post(String url, Object form) throws Exception {
		return post(url, form, null);
	}
	
	public String post(String url, Object form, Map<String, String> headers) throws Exception {
	    String input = JsonConverter.objectToJson(form, true);
	    log.debug("input json >>--{}--<<", input);
	    
	    HttpPost post = new HttpPost(url);
	    HttpEntity entity = null;
	    
	    if(input != null){
		    entity = new StringEntity(input, ContentType.APPLICATION_JSON);
		    post.setEntity(entity);
	    }
	    
	    addHeader(post, headers);
	    
	    HttpResponse response = client.execute(post);
	    log.debug("response status is {}", response.getStatusLine());
	    
	    entity = response.getEntity();
	    String output = EntityUtils.toString(entity);
	    log.debug("response is >>--{}--<<", output);
	    
	    return output;
	}
	
	public String post(String url, List<NameValuePair> nvps) throws Exception {
		return post(url, nvps, null);
	}
	
	public String post(String url, Map<String, String> params) throws Exception {
		List<NameValuePair> nvps = null;
		
		if(DataUtils.getSize(params) > 0){
			Set<Entry<String, String>> entries = params.entrySet();
			nvps = new LinkedList<NameValuePair>();
			
			for(Entry<String, String> entry : entries){
				nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		
		return post(url, nvps);
	}

	public String post(String url, List<NameValuePair> nvps, Map<String, String> headers) throws Exception {
		log.debug("input name pairs >>--{}--<<", nvps);
		
	    HttpPost post = new HttpPost(url);
	    
	    if(nvps != null){
	    	post.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
	    }
	    
	    addHeader(post, headers);
	    
	    HttpResponse response = client.execute(post);
	    log.debug("response status is {}", response.getStatusLine());
	    
	    HttpEntity entity = response.getEntity();
	    String output = EntityUtils.toString(entity);
	    log.debug("response is >>--{}--<<", output);
	    
	    return output;
	}

	public String get(String url, Map<String, String> query, Map<String, String> headers) throws Exception {
		log.debug("query pairs is [{}]", query);
		
		List<NameValuePair> params = null;
		
		if(query != null && query.size() > 0){
			params = new ArrayList<>();
			
			Iterator<String> it = query.keySet().iterator();
			while(it.hasNext()){
				String name = it.next();
				String value = query.get(name);
				
				params.add(new BasicNameValuePair(name, value));
			}
		}
		
		
		HttpGet get;
		
		if(CollectionUtils.isEmpty(params)){
			get = new HttpGet(url);
		}else{
			get = new HttpGet(url + "?" + URLEncodedUtils.format(params, Consts.UTF_8));
		}
		
		addHeader(get, headers);
		
		HttpResponse response = client.execute(get);
		log.debug("response status is {}", response.getStatusLine());
		
		HttpEntity entity = response.getEntity();
	    String output = EntityUtils.toString(entity);
	    log.debug("response is <<{}>>", output);
	    
	    return output;
	}
	
	public String get(String url) throws Exception {
		return get(url, null, null);
	}
	
//	public String get(Map<String, String> query, String url) throws Exception {
//		if(query != null && query.size() > 0){
//			List<NameValuePair> params = new ArrayList<>();
//			
//			Iterator<String> it = query.keySet().iterator();
//			while(it.hasNext()){
//				String name = it.next();
//				String value = query.get(name);
//				
//				params.add(new BasicNameValuePair(name, value));
//			}
//		}
//		
//		return get(url, query, null);
//	}
	
	public String get(String url, Map<String, String> query) throws Exception {
		return get(url, query, null);
	}
	
	void addHeader(HttpMessage msg, Map<String, String> headers){
	    if(headers != null && headers.size() > 0){
	    	Iterator<String> keys = headers.keySet().iterator();
	    	while(keys.hasNext()){
	    		String key = keys.next();
	    		String value = headers.get(key);
	    		
	    		msg.addHeader(key, value);
	    	}
	    }
	}
}
